//==============================================================================
// Copyright (c) 2008-2013 Niall Ryan. All Rights Reserved.
//==============================================================================

#ifndef HYDRA_BACKOFF_H
#define HYDRA_BACKOFF_H 1

#include "hydra/thread/Thread.h"

namespace Hydra
{
	/**
	 * Exponential backoff implementation. Call wait() when under contention, to give other threads a chance to
	 * release their resources. The first few calls to wait() will call this_thread::pause() with exponentially
	 * increasing loop counts, this will allow threads on other processors and hyperthreaded cores to complete. Subsequent
	 * calls to wait() will call this_thread::yield() instead, this will allow threads running on the same core to
	 * complete.
	 */
	class Backoff
	{
	public:
		Backoff() : m_count(1) { }

		void wait()
		{
			if( m_count <= MAX_PAUSE_LOOPS )
			{
				this_thread::pause(m_count);
				m_count <<= 1;
			}
			else
			{
				this_thread::yield();
			}
		}

		void reset()
		{
			m_count = 1;
		}

	private:
		static const int MAX_PAUSE_LOOPS = 32;
		int m_count;
	};
}

#endif
